#!/bin/sh
exec 2>>error.log
. shcgi/cgilite.sh
mkdir -p users
#env >>debug
printf 'POST: %s\n' "$cgilite_post" >>debug
printf 'action: %s\n' "$(GET action)" >>debug
wget="$(which wget)"
wget(){ "$wget" -T 5 -t 1 -q -U '' $@; }
checkid(){ grep -m 1 -xE '[0-9a-zA-Z:_]{12}'; }
genid(){
# generate random ID
head -c9 /dev/urandom \
| uuencode -m - \
| sed -n '2{y;+/;:_;;p}'
}
timeid(){
# generate time based ID
d=$(date +%s)
{ printf $(
while [ "$d" -gt 0 ]; do
printf \\%o $((d % 256))
d=$((d / 256))
done
) | tac
head -c5 /dev/urandom
} \
| uuencode -m - \
| sed -n '2{y;+/;:_;;p}'
}
getFavicon(){
url="$1"
bid="$2"
prot=${url%%://*}
domain="${url#*://}"
domain="${domain%%/*}"
ubase="${prot}://${domain}"
file="${BDB}/favicons/${bid}.ico"
mkdir -p "${BDB}/favicons/" && chmod a+rx "${BDB}/favicons/"
favinfo="$(
wget -O- "$url" \
| head -c4096 \
| sed -rn \
's;^.*(<[Ll][Ii][Nn][Kk]( [^>]*)? [Rr][Re][Ll]='\''([Ss][Hh][Oo][Rr][Tt][Cc][Uu][Tt] )?[Ii][Cc][Oo][Nn]'\''[^>]*>).*$;\1;;
s;^.*(<[Ll][Ii][Nn][Kk]( [^>]*)? [Rr][Re][Ll]="([Ss][Hh][Oo][Rr][Tt][Cc][Uu][Tt] )?[Ii][Cc][Oo][Nn]"[^>]*>).*$;\1;;
tX; b; :X;
s;^.*<([^>]+) [Hh][Rr][Ee][Ff]="([^"]+)".*$:\2;;
s;^.*<([^>]+) [Hh][Rr][Ee][Ff]='\''([^'\'']+)'\''.*$:\2;;
tY; b; :Y; p
'
)"
printf 'Shortcut icon for %s is %s\n' "$url" "$favinfo" >>debug
[ -z "$favinfo" ] && favinfo="${ubase}/favicon.ico"
case "$favinfo" in
http://*|https://*|//*) wget -O "$file" "$favinfo"
;;
/*) wget -O "$file" "${ubase}/${favinfo}"
;;
*) wget -O "$file" "${url%/*}/${favinfo}"
;;
esac
[ -f "${file}.1" ] && mv "${file}.1" "$file"
chmod a+r "$file"
}
list_folders(){
head -qn1 "${BDB}"/????????????.bm \
| sort -nk3 \
| cut -f1,2
}
order_files(){
n=1000
list_folders \
| while read fid nan; do
file="${BDB}/${fid}.bm"
sed -ri "1s;^(([^\t]+\t){2})[^\t]+(.*)$;\1${n}\3;;" "$file"
n=$((n + 1000))
done
}
COKID="$(COOKIE id |checkid)"
QRYID="$(GET id |checkid)"
BDB="users/${COKID}"
if [ -n "$QRYID" ]; then
printf '%s 303 See Other\r\n' "$SERVER_PROTOCOL"
printf 'Location: %s\r\n' "${SCRIPT_NAME}"
SET_COOKIE +8640000 "id=${QRYID}"
printf '\r\n'
exit 0
elif [ -z "$COKID" -a -z "$QRYID" ]; then
printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
cat <<-EOF
Bookman - New Collection
You have not yet set up a collection on this server.
Click here to start a new collection.
EOF
exit 0
elif ! [ -d "${BDB}" ]; then
printf '%s 404 Not Found\r\n' "$SERVER_PROTOCOL"
printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
cat <<-EOF
Bookman - 404
The collection you requested does not exist on this server.
Click here to start a new collection.
EOF
exit 0
fi
case "$(GET action)" in
newid)
NEWID="$(genid)"
{ git init "users/${NEWID}" || mkdir -p "users/${NEWID}"; } >&-
printf '%s 303 See Other\r\n' "$SERVER_PROTOCOL"
printf 'Location: %s\r\n' "${SCRIPT_NAME}?id=${NEWID}"
SET_COOKIE +8640000 "id=${NEWID}"
printf '\r\n'
exit 0
;;
newfolder)
name="$(POST name |head -n1)"
fid="$(timeid)"
order="$(
head -qn1 "${BDB}"/????????????.bm \
| cut -f3 \
| sort -n \
| tail -n1 \
|| printf 1
)"
order="$(((order + 1000) / 1000 * 1000))"
if [ -n "$name" -a -d "${BDB}" ]; then
printf '%s\t%s\t%s\n' "$fid" "$(HTML "$name")" "$order" >"${BDB}/${fid}.bm"
fi
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
modfolder)
name="$(POST name |head -n1)"
fid="$(POST fid | checkid)"
file="${BDB}/${fid}.bm"
if [ "$(POST control)" = confirm -a -n "$name" -a -f "$file" ]; then
sed -ri "1s'^(${fid}\t)[^\t]+(\t.+)$'\1${name}\2';" "$file"
fi
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
delfolder)
fid="$(POST fid | checkid)"
target="$(POST target | checkid)"
file="${BDB}/${fid}.bm"
tfile="${BDB}/${target}.bm"
if [ "$(POST control)" = confirm -a -f "$file" ]; then
if [ "$target" = "____________" ] || tail -n+2 "$file" >>"$tfile"; then
rm -f "$file"
fi
fi
REDIRECT "${SCRIPT_NAME}#${target}"
;;
movefolder)
fid="$(POST fid | checkid)"
target="$(POST target | checkid)"
file="${BDB}/${fid}.bm"
tfile="${BDB}/${target}.bm"
if [ "$target" = "____________" -a -f "$file" -a "$(POST control)" = confirm ]; then
read nan1 nan2 last nan3 <"${BDB}/$(list_folders |tail -n1 |cut -f1).bm"
sed -ri "1s;^(([^\t]+\t){2})[^\t]+(.*)$;\1$((${last:-0} + 1000))\3;;" "$file"
elif [ -f "$tfile" -a -f "$file" -a "$(POST control)" = confirm ]; then
read nan1 nan2 tid nan3 <"$tfile"
sed -ri "1s;^(([^\t]+\t){2})[^\t]+(.*)$;\1$((${tid:-1} -1))\2;;" "$file"
order_files
fi
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
newbookmark)
fid="$(POST fid | checkid)"
name="$(POST name |head -n1)"
url="$(POST url |head -n1)"
file="${BDB}/${fid}.bm"
bid="$(timeid)"
if [ -n "$name" -a -f "${file}" ]; then
printf '%s\t%s\t%s\n' "$bid" "$(HTML "$name")" "$url" >>"${file}"
fi
getFavicon "$url" "$bid"
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
modbookmark)
bid="$(POST bid | checkid)"
name="$(POST name |head -n1)"
url="$(POST url |head -n1)"
file="$(grep -lm1 "^${bid}" "${BDB}"/????????????.bm |head -n1)"
if [ -n "$name" -a -n "$url" -a "$(POST control)" = confirm -a -w "$file" ]; then
sed -rni "/^${bid}\t/!p; /^${bid}\t/i${bid}\t$(HTML "$name")\t${url}" "$file"
fi
getFavicon "$url" "$bid"
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
movebookmark)
bid="$(POST bid | checkid)"
fid="$(POST target | checkid)"
sfile="$(grep -lm1 "^${bid}" "${BDB}"/????????????.bm |head -n1)"
tfile="${BDB}/${fid}.bm"
if [ "$(POST control)" = confirm -a -n "$bid" -a -w "$sfile" -a -w "$tfile" ]; then
grep -m1 "^${bid}" "$sfile" >>"$tfile" \
&& sed -ri "0,/^${bid}/{/^${bid}/d;}" "$sfile"
fi
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
bmup)
fid="$(GET fid |checkid)"
bid="$(GET bid |checkid)"
file="${BDB}/${fid}.bm"
if [ -n "$bid" -a -n "$fid" ] && grep -q "^${bid}" "$file"; then
sed -ri ":X;\$bY;N;bX;:Y; s;(\n[^\n]+)(\n${bid}\t[^\n]+);\2\1;;" "$file"
fi
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
bmdn)
fid="$(GET fid |checkid)"
bid="$(GET bid |checkid)"
file="${BDB}/${fid}.bm"
if [ -n "$bid" -a -n "$fid" ] && grep -q "^${bid}" "$file"; then
sed -ri ":X;\$bY;N;bX;:Y; s;(\n${bid}\t[^\n]+)(\n[^\n]+);\2\1;;" "$file"
fi
REDIRECT "${SCRIPT_NAME}#${fid}"
;;
query)
fid="$(POST fid |checkid)"
bid="$(POST bid |checkid)"
file="${BDB}/${fid}.bm"
query="$(URL "$(POST query)")"
url="$(grep -m1 "^${bid}" "$file" |cut -f3-)"
urlpfx="${url%\{@\}*}"
urlsfx="${url#*\{@\}}"
REDIRECT "${urlpfx}${query}${urlsfx}"
;;
esac
bookmarkmod(){
bmod="$(GET bmodify |checkid)"
bmove="$(GET bmove |checkid)"
if [ -n "$bmod" ]; then
file="$(grep -lm1 "^${bmod}" "${BDB}/"????????????.bm |head -n1)"
read bid name url <<-EOF
$(grep -m1 "^${bmod}" "$file")
EOF
cat <<-EOF
EOF
elif [ -n "$bmove" ]; then
file="$(grep -lm1 "^${bmove}" "${BDB}/"????????????.bm |head -n1)"
read bid name url <<-EOF
$(grep -m1 "^${bmove}" "$file")
EOF
cat <<-EOF
EOF
fi
}
show_bookmarks(){
fid="$1"
bmodify="$(GET bmodify |checkid)"
tail -n+2 "${BDB}/${fid}.bm" \
| while read bid name url; do
if [ "${url%\{@\}*}" = "${url}" ]; then
cat <<-EOF
EOF
else
cat <<-EOF
EOF
fi
done
}
foldermod(){
fmodify="$(GET fmodify |checkid )"
fdelete="$(GET fdelete |checkid )"
fmove="$(GET fmove |checkid )"
if [ -n "$fmodify" ]; then
read fid fname order <"${BDB}/${fmodify}.bm"
cat <<-EOF
EOF
elif [ -n "$fdelete" ]; then
read fid fname order <"${BDB}/${fdelete}.bm"
cat <<-EOF
EOF
elif [ -n "$fmove" ]; then
read fid fname order <"${BDB}/${fmove}.bm"
cat <<-EOF
EOF
fi
}
show_folders(){
list_folders \
| while read fid fname order; do
file="${BDB}/${fid}.bm"
cache="${BDB}/${fid}.cache"
if [ "${cache}" -nt "${file}" ]; then
cat "$cache"
else
tee "$cache" <<-EOF
${fname}
Modify
$(show_bookmarks "$fid")
EOF
fi
done
}
SET_COOKIE +8640000 "id=${COKID}" # Refresh Cookie
printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
cat <
Bookman - Your Collection
$(foldermod)
$(bookmarkmod)
$(show_folders)
EOF
#set filetype=sh